#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#include "linux_keys.h"


#include <iostream>





using namespace std;

LinuxKeys::LinuxKeys(){
    init_keyboard();
}
LinuxKeys::~LinuxKeys(){
    close_keyboard();
}

//  struct termios
//    {
//      tcflag_t c_iflag;		/* input mode flags */
//      tcflag_t c_oflag;		/* output mode flags */
//      tcflag_t c_cflag;		/* control mode flags */
//      tcflag_t c_lflag;		/* local mode flags */
//      cc_t c_line;			/* line discipline */
//      cc_t c_cc[NCCS];		/* control characters */
//      speed_t c_ispeed;		/* input speed */
//      speed_t c_ospeed;		/* output speed */
//  #define _HAVE_STRUCT_TERMIOS_C_ISPEED 1
//  #define _HAVE_STRUCT_TERMIOS_C_OSPEED 1
//    }
//
//  refernce:https://man7.org/linux/man-pages/man3/termios.3.html
//  Raw_mode:
//           termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
//                           | INLCR | IGNCR | ICRNL | IXON);
//           termios_p->c_oflag &= ~OPOST;
//           termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
//           termios_p->c_cflag &= ~(CSIZE | PARENB);
//           termios_p->c_cflag |= CS8;
void LinuxKeys::init_keyboard(){
    tcgetattr(STDIN_FILENO,&initial_settings); 

    termios new_settings;
    new_settings = initial_settings;           
    new_settings.c_iflag &= ~(BRKINT|ICRNL|INPCK|ISTRIP|IXON);
    //new_settings.c_oflag &= ~(OPOST);
    new_settings.c_cflag |= CS8;
    new_settings.c_lflag &= ~(ICANON|ECHO|ISIG|IEXTEN);
    new_settings.c_cc[VTIME] = 0;
    new_settings.c_cc[VMIN] = 0;
    
    tcsetattr(STDIN_FILENO,TCSANOW,&new_settings);
}


void LinuxKeys::close_keyboard(){
    tcsetattr(STDIN_FILENO,TCSANOW,&initial_settings);
}



int LinuxKeys::ReadOneChar(char* c){
    return read(STDIN_FILENO,c,1);
}

int LinuxKeys::GetKeyCode()
{
    int nread;
    char c;
    while((nread = read(STDIN_FILENO,&c,1))==0);
    if (nread == -1) exit(1);
#ifdef OUTPUT_KEYCODE
    cout<<"LinuxKeys read keyint:"<<to_string((int)c)<<endl;
#endif
    return (int)c;
    //return getchar();
}



/* refernce:https://github.com/antirez/kilo/blob/master/kilo.c
 * Read a key from the terminal put in raw mode, trying to handle
 * escape sequences. */
//int editorReadKey(int fd) {
//    int nread;
//    char c, seq[3];
//    while ((nread = read(fd,&c,1)) == 0);
//    if (nread == -1) exit(1);
//
//    while(1) {
//        switch(c) {
//        case ESC:    /* escape sequence */
//            /* If this is just an ESC, we'll timeout here. */
//            if (read(fd,seq,1) == 0) return ESC;
//            if (read(fd,seq+1,1) == 0) return ESC;
//
//            /* ESC [ sequences. */
//            if (seq[0] == '[') {
//                if (seq[1] >= '0' && seq[1] <= '9') {
//                    /* Extended escape, read additional byte. */
//                    if (read(fd,seq+2,1) == 0) return ESC;
//                    if (seq[2] == '~') {
//                        switch(seq[1]) {
//                        case '3': return DEL_KEY;
//                        case '5': return PAGE_UP;
//                        case '6': return PAGE_DOWN;
//                        }
//                    }
//                } else {
//                    switch(seq[1]) {
//                    case 'A': return ARROW_UP;
//                    case 'B': return ARROW_DOWN;
//                    case 'C': return ARROW_RIGHT;
//                    case 'D': return ARROW_LEFT;
//                    case 'H': return HOME_KEY;
//                    case 'F': return END_KEY;
//                    }
//                }
//            }
//
//            /* ESC O sequences. */
//            else if (seq[0] == 'O') {
//                switch(seq[1]) {
//                case 'H': return HOME_KEY;
//                case 'F': return END_KEY;
//                }
//            }
//            break;
//        default:
//            return c;
//        }
//    }
//}
    

